home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Language/OS - Multiplatform Resource Library
/
LANGUAGE OS.iso
/
lisp
/
eulisp
/
mpfeel.lha
/
MPFeel
/
Modules
/
defs.em
< prev
next >
Wrap
Lisp/Scheme
|
1992-10-06
|
12KB
|
386 lines
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; EuLisp Module Copyright (C) University of Bath 1991 ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Name: defs ;;
;; ;;
;; Author: Keith Playford ;;
;; ;;
;; Date: 21 August 1990 ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; Change Log:
;; Version 1.0 (21/8/90)
;;
;; Lisp version of defclass... */
(defmodule defs
(lists ccc calls list-operators arith
(except (defcondition) errors )
symbols others macros0 extras0
(except (defclass defstruct) classes)
(except (null) class-names)
streams)
()
;; 'defstruct'...
;; Utils...
(defconstant *key-list-fail* nil)
(defconstant *nothing* (gensym))
(defun search-key-list (l k)
(cond ((null l) *key-list-fail*)
((eqcar l k) (cadr l))
(t (search-key-list (cddr l) k))))
(defconstant invalid-slot-options
(make-instance condition-class
'name 'invalid-slot-options
'direct-superclasses (list condition)
'direct-slot-descriptions
`((name options
initargs (options)
initform ,(lambda () ())
slot-class ,local-slot-description))))
(deflocal *name* nil)
(deflocal *readers* nil)
(deflocal *writers* nil)
(deflocal *accessors* nil)
(defun reset ()
(setq *name* nil)
(setq *readers* nil)
(setq *writers* nil)
(setq *accessors* nil))
(defun canonicalise (ops def-slot-class)
(when (symbolp ops) (setq ops (list ops)))
(unless (consp ops) (error "slot options not a list"
invalid-slot-options 'options ops))
(let ((name *nothing*)
(slot-class def-slot-class)
(slot-initargs *nothing*)
(initform *nothing*)
(initargs nil)
(readers nil)
(writers nil)
(accessors nil))
(labels
((inner (l)
(unless (null l)
(let ((key (car l))
(val (cadr l)))
(cond ((eq key 'initarg)
(setq initargs (nconc initargs (list val))))
((eq key 'initform)
(if (eq initform *nothing*)
(setq initform `(lambda () ,val))
(error "bad initform"
invalid-slot-options 'options ops)))
((eq key 'slot-class)
(if (eq slot-class def-slot-class)
(setq slot-class val);;do find-dbclass of val
(error "slot-class multiply defined"
invalid-slot-options 'options ops)))
((eq key 'slot-initargs)
(if (eq slot-initargs *nothing*)
(setq slot-initargs val);; was class-initargs
(error "slot initargs multiply defined"
invalid-slot-options 'options ops)))
((eq key 'reader)
(setq readers (cons (cons val name) readers)))
((eq key 'writer)
(setq writers (cons (cons val name) writers)))
((eq key 'accessor)
(setq accessors (cons (cons val name) accessors)))
(t (error "unknown slot option"
invalid-slot-options 'options ops))))
(inner (cddr l)))))
(setq name (car ops))
(inner (cdr ops))
(setq *readers* (nconc readers *readers*))
(setq *writers* (nconc writers *writers*))
(setq *accessors* (nconc accessors *accessors*))
(when (eq slot-class *nothing*)
(setq slot-class 'local-slot-description))
(when (eq slot-initargs *nothing*)
(setq slot-initargs nil))
(nconc `(list 'name ',name
'slot-class ,slot-class
,@slot-initargs
'initargs ',initargs)
(if (eq initform *nothing*) nil `('initform ,initform))))))
(defun reader-defs (o)
(mapcar
(lambda (pair)
`(defconstant ,(car pair) (make-reader ,*name* ',(cdr pair))))
*readers*))
(defun writer-defs (o)
(mapcar
(lambda (pair)
`(defconstant ,(car pair) (make-writer ,*name* ',(cdr pair))))
*writers*))
(defun accessor-defs (o)
(mapcar
(lambda (pair)
`(progn
(defconstant ,(car pair) (make-reader ,*name* ',(cdr pair)))
((setter setter) ,(car pair) (make-writer ,*name* ',(cdr pair)))))
*accessors*))
(defun make-constructor-initarg-list (ll)
(if (not (consp ll)) ()
(cons (list 'quote (car ll))
(cons (car ll) (make-constructor-initarg-list (cdr ll))))))
(defun improper-list-p (l)
(if (not (consp l)) l (improper-list-p (cdr l))))
(defun make-positional-constructor-def (spec)
(let* ((name (car spec))
(ll (cdr spec))
(tail (improper-list-p ll)))
(if (null tail)
`(defun ,name ,ll
(make-instance ,*name*
,@(make-constructor-initarg-list ll)))
`(defun ,name ,ll
(apply
make-instance
,*name*
(nconc (list ,@(make-constructor-initarg-list ll)) ,tail))))))
(defun constructor-defs (o)
(cond ((null o) nil)
((null (cdr o)) (error "unbalance class ops"
invalid-slot-options 'options o))
((eqcar o 'constructor)
(let ((spec (car (cdr o))))
(if (not (consp spec))
(cons (make-positional-constructor-def (cons spec 'args))
(constructor-defs (cddr o)))
(cons (make-positional-constructor-def spec)
(constructor-defs (cddr o))))))
((eqcar o 'predicate)
(cons `(progn
(defgeneric ,(car (cdr o)) (obj))
(defmethod ,(car (cdr o)) ((obj object)) ())
(defmethod ,(car (cdr o)) ((obj ,*name*)) obj))
(constructor-defs (cddr o))))
(t (constructor-defs (cddr o)))))
(defun quotify-alternate (l)
(if (null l) ()
(cons (list 'quote (car l))
(cons (car (cdr l))
(quotify-alternate (cdr (cdr l)))))))
(defun metaclass-initargs (ops)
(let ((args (search-key-list ops 'metaclass-initargs)))
(unless (eq args *key-list-fail*)
(quotify-alternate args))))
(defmacro defstruct (name super slot-ops . class-ops)
(reset)
(setq *name* name)
`(progn
(defconstant ,name
(make-instance structure-class
'name ',name
'direct-superclasses ,(if super `(list ,super) '(list structure))
'direct-slot-descriptions
(list ,@(mapcar (lambda (x) (canonicalise x 'local-slot-description))
slot-ops))
'metaclass-hypotheses nil))
,@(reader-defs slot-ops)
,@(writer-defs slot-ops)
,@(accessor-defs slot-ops)
,@(constructor-defs class-ops)
',name))
(export defstruct)
(defmacro defclass (name supers slot-ops . class-ops)
(reset)
(setq *name* name)
(let ((metaclass
(or (search-key-list class-ops 'metaclass) 'class))
(initargs
(or (search-key-list class-ops 'metaclass-initargs) nil))
(slot-class (or (search-key-list class-ops 'default-slot-class)
'local-slot-description)))
`(progn
(defconstant ,name
(make-instance ,metaclass
'name ',name
'direct-superclasses ,(if supers `(list ,@supers) '(list object))
'direct-slot-descriptions
(list ,@(mapcar (lambda (x) (canonicalise x slot-class))
slot-ops))
'metaclass-hypotheses ()
,@(metaclass-initargs class-ops)))
,@(reader-defs slot-ops)
,@(writer-defs slot-ops)
,@(accessor-defs slot-ops)
,@(constructor-defs class-ops)
',name)))
(export defclass)
(defmacro defreader (name class slot)
`(defconstant ,name (make-reader ,class ',slot)))
(defmacro defwriter (name class slot)
`(defconstant ,name (make-writer ,class ',slot)))
(defmacro defaccessor (name class slot)
`(progn
(defconstant ,name (make-reader ,class ',slot))
((setter setter) ,name (make-writer ,class ',slot))))
(defmacro defpredicate (name class)
`(progn
(defgeneric ,name (x))
(defmethod ,name ((x object)) ())
(defmethod ,name ((x ,class)) x)))
(export defreader defwriter defaccessor defpredicate)
(defun method-extra-args ()
(if (compile-time-p)
()
(list '***method-status-handle*** '***method-args-handle***)))
(defun sll-signature (ll)
(cond ((not (consp ll)) nil)
((consp (car ll)) (cons (cadar ll) (sll-signature (cdr ll))))
(t (cons 'object (sll-signature (cdr ll))))))
(defun sll-formals (ll)
(cond ((null ll) nil)
((not (consp ll)) ll)
((consp (car ll)) (cons (caar ll) (sll-formals (cdr ll))))
(t (cons (car ll) (sll-formals (cdr ll))))))
(defun gf-class (ops)
(let ((val (search-key-list ops 'class)))
(if (eq val *key-list-fail*) 'generic-function val)))
(defun gf-method-class (ops)
(let ((val (search-key-list ops 'method-class)))
(if (eq val *key-list-fail*) 'method val)))
(defun gl-name (ops)
(let ((val (search-key-list ops 'name)))
(if (eq val *key-list-fail*) '*unnamed-lambda* val)))
(defun gf-methods (ops mc)
(let ((val (search-key-list ops 'methods)))
(if (eq val *key-list-fail*) nil
`(list
,@(mapcar
(lambda (form)
`(make-instance ,mc
'signature (list ,@(sll-signature (car form)))
'function
(lambda (,@(method-extra-args)
,@(sll-formals (car form)))
,@(cdr form))))
val)))))
(defmacro defgeneric (name ll . ops)
`(,@(if (symbolp name) (list 'defconstant name)
(list `(setter setter) (car (cdr name))))
(make-instance ,(gf-class ops)
'name ',name
'lambda-list ',ll
'method-class ,(gf-method-class ops)
'methods ,(gf-methods ops (gf-method-class ops)))))
(export defgeneric)
(defmacro defmethod (name sll . body)
`(progn
(add-method
,name
(make-instance (generic-function-method-class ,name)
'signature (list ,@(sll-signature sll))
'function
(lambda ,(append (method-extra-args)
(sll-formals sll))
,@body)))))
(export defmethod)
(defun defcondition-slot-descriptions (l)
(if (null l) nil
(cons `(list 'name ',(car l)
'slot-class local-slot-description
'initargs ',(list (car l))
'initform (lambda () ,(cadr l)))
(defcondition-slot-descriptions (cddr l)))))
(defmacro defcondition (name super . pairs)
`(defconstant ,name
(make-instance condition-class
'name ',name
'direct-superclasses (list ,(if super super 'condition))
'direct-slot-descriptions
(list ,@(defcondition-slot-descriptions pairs)))))
(export defcondition)
(defmacro call-next-method ()
(if (compile-time-p)
'(call-method-by-list (method-method-list)
(method-arg-list))
'(if ***method-status-handle***
(progn ;;(format t "Call next: ~a ~a\n"
;;***method-status-handle***
;; ***method-args-handle***)
(apply call-method-by-list
(list ***method-status-handle***
***method-args-handle***)))
(error "No Next Method" Internal-Error nil))))
(defmacro next-method-p ()
(if (compile-time-p)
(progn (error "Next-method-p: not implemented" clock-tick)
nil)
'***method-status-handle***))
(export next-method-p)
(defmacro generic-lambda (args . ops)
`(make-instance ,(gf-class ops)
'name ',(gl-name ops)
'lambda-list ',args
'method-class ,(gf-method-class ops)
'methods ,(gf-methods ops (gf-method-class ops))))
(export call-next-method generic-lambda)
)